package com.li.sqlparse.service.impl;

import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.statement.SQLBlockStatement;
import com.alibaba.druid.sql.ast.statement.SQLCreateTriggerStatement;
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
import com.alibaba.druid.sql.ast.statement.SQLIfStatement;
import com.li.sqlparse.entity.ParseItemDto;
import com.li.sqlparse.entity.SetDeclareItemDto;
import com.li.sqlparse.entity.SqlConstant;
import com.li.sqlparse.service.SqlParseHelperService;
import com.li.sqlparse.service.SqlParseService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * @author LiDong
 * @version 1.0.0
 * @className BaseParseServiceImpl.java
 * @createTime 2021年06月04日 22:06:00
 */
public class SqlParseHelperServiceImpl implements SqlParseHelperService {

    private static final Logger logger = LoggerFactory.getLogger(SqlParseHelperServiceImpl.class);

    /**
     * 校验触发器Sql
     *
     * @param sql
     * @param dbType
     * @return
     */
    @Override
    public boolean checkTriggerSql(String sql, String dbType) {
        // 校验是否为触发器Sql
        boolean flag = true;
        try {
            List<SQLStatement> list = SQLUtils.parseStatements(sql, dbType);
            for (SQLStatement sqlStatement : list) {
                if (sqlStatement instanceof SQLCreateTriggerStatement) {
                    flag = false;
                    break;
                }
            }
        } catch (Exception e) {
            logger.error("Error Occur:{}", e.getMessage());
        }
        return flag;
    }

    /**
     * 解析 sql 语句
     *
     * @param sql                sql
     * @param dbType
     * @param setSelectColumns   set 语句中column 对象
     * @param setFromTables      set 语句中table 对象
     * @param setDeclareItemDtos set 语句对象
     * @param parseItems         一条语句被解析出的对象
     * @param sqlParseService    sqlParseService
     */
    @Override
    public void dealSqlParse(String sql, String dbType, Set<String> setSelectColumns, Set<String> setFromTables, List<SetDeclareItemDto> setDeclareItemDtos, List<ParseItemDto> parseItems, SqlParseService sqlParseService) {
        List<SQLStatement> list;
        try {
            list = SQLUtils.parseStatements(sql, dbType);
        } catch (Exception e) {
            logger.error("触发器sql校验出错，druid解析器无法解析：{}", e.getMessage());
            return;
        }
        try {
            // 创建触发器语句中一个分号结束的sql为一个SQLStatement
            for (SQLStatement sqlStatement : list) {
                // 触发器 On 的对象
                SQLExprTableSource triggerOn = ((SQLCreateTriggerStatement) sqlStatement).getOn();
                // 触发器 Begin End 之间的Sql
                SQLStatement triggerBody = ((SQLCreateTriggerStatement) sqlStatement).getBody();
                List<SQLStatement> statementList = ((SQLBlockStatement) triggerBody).getStatementList();
                for (SQLStatement statement : statementList) {
                    // 处理SQL 中IF ELSE格式的语句
                    if (statement instanceof SQLIfStatement) {
                        List<SQLStatement> statements = ((SQLIfStatement) statement).getStatements();
                        for (SQLStatement sqlIfStatement : statements) {
                            dealParseItems(sqlIfStatement, setFromTables, setSelectColumns, setDeclareItemDtos, parseItems, sqlParseService);
                        }
                    } else {
                        dealParseItems(statement, setFromTables, setSelectColumns, setDeclareItemDtos, parseItems, sqlParseService);
                    }
                }
                ParseItemDto parseItem = new ParseItemDto();
                parseItem.setId(String.valueOf(0));
                parseItem.setFrom(String.valueOf(triggerOn));
                parseItems.add(parseItem);
            }
            // 解析 parseItems 中 from 是sql 语句的情况
            for (ParseItemDto parseItem : parseItems) {
                List<ParseItemDto> children = new ArrayList<>();
                List<ParseItemDto> parseItemsChildren = sqlParseService.dealParseItems(parseItem, null, children);
                parseItem.setChildren(parseItemsChildren);
            }
        } catch (Exception e) {
            logger.error("Error Occur:{}", e.getMessage());
        }
    }

    /**
     * 处理parseItems
     *
     * @param statement          statement
     * @param setFromTables      set语句包含的表
     * @param setSelectColumns   set语句包含的字段
     * @param setDeclareItemDtos setdeclare 对象
     * @param parseItems         Sql解析对象
     * @param sqlParseService    sqlParseService
     */
    private void dealParseItems(SQLStatement statement, Set<String> setFromTables, Set<String> setSelectColumns, List<SetDeclareItemDto> setDeclareItemDtos, List<ParseItemDto> parseItems, SqlParseService sqlParseService) {
        if (statement instanceof SQLIfStatement) {
            List<SQLStatement> statements = ((SQLIfStatement) statement).getStatements();
            for (SQLStatement sqlStatement : statements) {
                dealParseItems(sqlStatement, setFromTables, setSelectColumns, setDeclareItemDtos, parseItems, sqlParseService);
            }
        }
        String statementSql = String.valueOf(statement).toUpperCase().trim();
        if (statementSql.startsWith(SqlConstant.DECLARE)) {
            // declare 开头的直接跳过 sql 中 set开头的语句处理
            try {
                sqlParseService.dealSqlDeclare(statement, setFromTables, setSelectColumns, setDeclareItemDtos);
            } catch (Exception e) {
                logger.error("解析触发器Declare语句出错:{}", e.getMessage());
            }
        } else if (statementSql.startsWith(SqlConstant.SET)) {
            // declare 开头的直接跳过 sql 中 set开头的语句处理
            try {
                sqlParseService.dealSqlSet(statement, setFromTables, setSelectColumns, setDeclareItemDtos);
            } catch (Exception e) {
                logger.error("解析触发器Set语句出错:{}", e.getMessage());
            }
        } else if (statementSql.startsWith(SqlConstant.INSERT)) {
            // insert sql 处理
            try {
                sqlParseService.dealSqlInsert(statement, parseItems);
            } catch (Exception e) {
                logger.error("解析触发器Insert语句出错:{}", e.getMessage());
            }
        } else if (statementSql.startsWith(SqlConstant.CREATE)) {
            // create 语句处理
            try {
                sqlParseService.dealSqlCreate(statement, parseItems);
            } catch (Exception e) {
                logger.error("解析触发器Create语句出错:{}", e.getMessage());
            }
        } else if (statementSql.startsWith(SqlConstant.SELECT) && statementSql.contains(SqlConstant.INTO)) {
            // select into 语句处理
            try {
                sqlParseService.dealSqlSelectInto(statement, parseItems);
            } catch (Exception e) {
                logger.error("解析触发器SelectInto语句出错:{}", e.getMessage());
            }
        }
    }

}
